<?php

namespace app\common\service;

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

use think\facade\Cache;
use think\Exception;
use UnexpectedValueException;

class AuthToken
{

    function __construct()
    {

    }

    /**
     * Token配置
     *
     * @return array
     */
    public static function config()
    {
        return [
            'token_key' => 'php-jwt@uniqid#123456',
            'token_exp' => 1
        ];
    }

    /**
     * Token生成
     *
     * @param array $data 自定义参数数组
     * @param integer $expires 必填 token过期时间 单位:秒 例子：7200=2小时
     * @param string $scopes 选填 token标识，请求接口的token
     * @return string
     */
    public static function create($data, $expires, $scopes = '')
    {
        //JWT标准规定的声明，但不是必须填写的；
        //iss: jwt签发者
        //sub: jwt所面向的用户
        //aud: 接收jwt的一方
        //exp: jwt的过期时间，过期时间必须要大于签发时间
        //nbf: 定义在什么时间之前，某个时间点后才能访问
        //iat: jwt的签发时间
        //jti: jwt的唯一身份标识，主要用来作为一次性token。
        $config = self::config();

        try {
            $time = time();
            $payload = [
                'iat' => $time, // 签发时间
                'nbf' => $time, // 生效时间
                //'exp' => time() + $config['token_exp'] * 3600, // 过期时间
                'exp' => $expires,
                'data' => $data,
            ];
            //$payload['iss']=''; // 签发者 可选
            //$payload['aud']=''; // 接收该JWT的一方，可选
            if ($scopes) {
                $payload['scopes'] = $scopes; // token标识，请求接口的token
            }

            $key = $config['token_key']; // 密钥
            $token = JWT::encode($payload, $key, 'HS256');

            return $token;
        } catch (\Firebase\JWT\ExpiredException | \Exception $e) {
            return ['status' => 104, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     * Token验证
     *
     * @param string $token token
     */
    public static function verify($token)
    {
        $config = self::config();

        try {
            $key = $config['token_key'];
            $decode = JWT::decode($token, new Key($key, 'HS256'));
            $admin = $decode->data;

            return $admin;
        } catch (\Firebase\JWT\SignatureInvalidException $e) {
            // 签名不正确
            return ['status' => 101, 'msg' => $e->getMessage(), 'data' => '签名不正确'];
        } catch (\Firebase\JWT\BeforeValidException $e) {
            // 签名在某个时间点之后才能用
            return ['status' => 102, 'msg' => $e->getMessage(), 'data' => '签名在某个时间点之后才能用'];
        } catch (\Firebase\JWT\ExpiredException $e) {
            // token过期
            return ['status' => 103, 'msg' => $e->getMessage(), 'data' => 'token过期'];
        } catch (Exception | UnexpectedValueException $e) {
            return ['status' => 0, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }
}
